<?php
namespace app\index\controller;

use app\common\model\coin\CoinList;
use app\common\model\trade\TradeCnySales;
use app\common\model\trade\TradeCnyBuy;
use app\common\model\trade\TradeMate;
use think\Exception;
use app\common\controller\Param;
use app\common\controller\Base64;
use app\common\model\user\Users;
use app\common\model\trade\TradeCoinBuy;
use app\common\model\coin\CoinUser;
use think\Db;
use app\common\model\trade\TradeComplain;
use think\Config;

class Tradecny extends Base
{
    private $param;
    public function _initialize()
    {
        parent::_initialize();
        $this->param = Param::getParam($this->user_id);
    }
    /**
     * 获取币种列表
     * @return unknown
     */
    public function getCoinList()
    {
        $list = CoinList::where(['state' => 1])->select();
        foreach ($list as &$rows) {

        }
        return jsonSuccess($list);
    }

    /**
     * 挂卖，求购列表
     * @return unknown
     */
    public function getTradeInfo()
    {
        $data = $this->reqeust->post('');
        //初始化查询条件
        $where = empty($data['user_select']) ?  ['surplus_num'=> ['gt',0],'state' => 1,'user_id' => ['neq',$this->user_id]] : ['user_id' => $this->user_id];
        if(!empty($data['coin']))$where['coin'] = $data['coin'];
        if($data['trade_style']) {
            //可出售列表
            $list = TradeCnyBuy::where($where)->order('id desc')->paginate()->toArray();
        } else {
            //可购买列表
            $list = TradeCnySales::where($where)->order('id desc')->paginate()->toArray();
        }
        foreach ($list['data'] as &$rows) {
            $rows['user_info'] = Users::get($rows['user_id']);
            $trade = $data['trade_style'] ? new TradeCoinBuy() : new TradeCnySales();
            $rows['trade_count'] = $trade -> where(['user_id' => $rows['user_id']])->count();
        }
        return jsonSuccess($list);
    }

    /**
     * 获取出售订单详情
     * @return unknown
     */
    public function getCnySalesInfo()
    {
    	$id = $this->request->post('id');
    	$info = TradeCnySales::get($id);
    	return jsonSuccess($info);
    }
    
    /**
     * 获取求购订单详情
     * @return unknown
     */
    public function getCnyBuyInfo()
    {
    	$id = $this->request->post('id');
    	$info = TradeCnyBuy::get($id);
    	return jsonSuccess($info);
    }
    
    /**
     * 获取匹配详情
     * @return unknown
     */
    public function getMateInfo()
    {
    	$id = $this->request->post('id');
    	$info = TradeMate::get($id);
    	//法币交易
    	if($info -> trade_type == 2) {
    		$trade_info = $info->source == 1 ? TradeCnyBuy::get($info -> source_id) : TradeCnySales::get($info -> source_id);
    		//获取交易的币种信息
    		$coin_id = $trade_info -> coin['id'];
    		$info = $info->toArray();
    		$info ['coin'] = CoinList::get($coin_id);
    	}
    	return jsonSuccess($info);
    }
    
    /**
     * 下架订单
     * @return unknown
     */
    public function downOrder()
    {
    	//获取客户端传递的数据
    	$data = $this->reqeust->post('');
    	Db::startTrans();
    	try {
    		$id = $data['id'];
    		if($data['param'] == 1 ) {
    			$this->downSales($id);
    		} elseif($data['param'] == 2) {
    			$this->downBuy($id);
    		}
    		Db::commit();
    	} catch (Exception $e) {
    		Db::rollback();
    		return jsonError($e->getMessage());
    	}
    	return jsonSuccess('下架成功');
    }
    
    /**
     * 下架出售订单
     * @param int $id 订单ID
     * @throws Exception
     */
    private function downSales($id)
    {
    	$sales_order = TradeCnySales::get($id);
    	if(!$sales_order->state)throw new Exception('状态错误');
    	//更改订单状态
    	$update = ['state' => 0,'update_time' => time()];
    	$sales_order -> save($update);
    	//返回剩余金额到用户账户
    	$user_coin = CoinUser::where(['user_id' => $this->user_id , 'coin_id' => $sales_order->coin->id])
    		->setInc('avalible_price',$sales_order->surplus_num);
    	//扣除冻结金额
    	$user_coin = CoinUser::where(['user_id' => $this->user_id , 'coin_id' => $sales_order->coin->id])
    		->setDec('freezing_price',$sales_order->surplus_num);
    }
    
    /**
     * 下架求购订单
     * @param int $id 订单ID
     * @throws Exception
     */
    private function downBuy($id)
    {
    	$buy_order = TradeCnyBuy::get($id);
    	if(!$buy_order->state)throw new Exception('状态错误');
    	//更改订单状态
    	$update = ['state' => 0,'update_time' => time()];
    	$buy_order -> save($update);
    }
    /**
     * 获取用户匹配订单
     * @return unknown
     */
    public function mateList()
    {
    	$where = ['sales_id' => $this->user_id,'trade_type' => 2];
    	$whereor = ['buy_id' => $this->user_id,'trade_type' => 2];
    	$list = TradeMate::where($where)->whereOr($whereor)->order('id desc')->paginate()->toArray();
    	foreach ($list['data'] as &$rows) {
    		$rows['user_id'] = $this->user_id; 
    	}
    	return jsonSuccess($list);
    }
    /**
     * 检测挂卖、求购参数是否合法
     * @param double $total_price 总金额
     * @param string $msg 提示文字
     * @param int $trade_style 交易类型0求购，1挂卖
     * @throws Exception
     */
    private function checkTradeParam($total_price,$msg,$trade_style)
    {
        //判断是否实名
        $user = Users::get($this->user_id);
        if(!$user->idcard)throw new Exception('请先实名认证');
        if($total_price < $this->param['trade_min_price'])throw new Exception("最小{$msg}金额不得低于{$this->param['trade_min_price']}");
        if($total_price > $this->param['trade_max_price'])throw new Exception("最大{$msg}金额不得高于{$this->param['trade_max_price']}");
        //判断今日挂卖单数是否超限
        $start_time = strtotime(date('Y-m-d').' 00:00:00');
        $end_time = strtotime(date('Y-m-d').' 23:59:59');
        if(!$trade_style){
            $count = TradeCnyBuy::where(['user_id' => $this->user_id,'create_time' => ['between',[$start_time,$end_time]]])->count();
        }else{
            $count = TradeCnySales::where(['user_id' => $this->user_id,'create_time' => ['between',[$start_time,$end_time]]])->count();
        }
        if($count >= $this->param['trade_max_num'])
            throw new Exception("每日最多{$msg}{$this->param['trade_max_num']}单");
        //计算当前时间是否可挂卖
        $start_time = strtotime($this->param['trade_start']);
        $end_time = strtotime($this->param['trade_end']);
        if(time() <  $start_time|| time() > $end_time )
            throw new Exception("当前不在{$msg}时间内");
    }

    /**
     * 添加求购订单
     * @throws Exception
     * @return unknown
     */
    public function addBuy()
    {
        $data = $this->reqeust->post('');
        try {
        	$this->checkReal($this->user_id);  //判断是否符合交易需求
            if(!$data['coin'])throw new Exception('请选择求购币种');
            if(!$data['buy_num'])throw new Exception('请输入求购数量');
            if(!$data['buy_price'])throw new  Exception('请输入求购单价');
            //判断挂卖是否符合系统设置
            $total_price = $data['buy_num'] * $data['buy_price'];  //计算当前订单法币金额
            $this->checkTradeParam($total_price,'求购',0);
            $out_trade_no = date('YmdHis').rand(10,99);
            //获取当前用户币币交易手续费
            $fee = $this->param['trade_fee'];
            $res = [
                'out_trade_no' => $out_trade_no,
                'user_id' => $this->user_id,
                'coin' => $data['coin'],
                'buy_num' => $data['buy_num'],
                'surplus_num' => $data['buy_num'],
                'buy_price' => $data['buy_price'],
                'fee' => $data['buy_num'] * ($fee / 100),
                'create_time' => time(),
                'update_time' => time()
            ];
            //添加求购记录
            TradeCnyBuy::create($res);
        } catch (Exception $e) {
            return jsonError($e->getMessage());
        }
        return jsonSuccess('求购成功');
    }

    /**
     * 添加挂卖订单
     * @throws Exception
     * @return unknown
     */
    public function addSale()
    {
        $data = $this->reqeust->post('');
        Db::startTrans();
        try {
        	$this->checkReal($this->user_id);  //判断是否符合交易需求
            if(!$data['coin'])throw new Exception('请选择挂卖币种');
            if(!$data['sales_num'])throw new Exception('请输入挂卖数量');
            if(!$data['sales_price'])throw new  Exception('请输入挂卖单价');
            //判断挂卖是否符合系统设置
            $total_price = $data['sales_num'] * $data['sales_price'];  //计算当前订单法币金额
            $this->checkTradeParam($total_price,'挂卖',1);
            $out_trade_no = date('YmdHis').rand(10,99);
            //获取当前用户币币交易手续费
            $fee = $this->param['trade_fee'];
            $real_num = $data['sales_num'] * (1 - ($fee / 100));
            $res = [
                'out_trade_no' => $out_trade_no,
                'user_id' => $this->user_id,
                'coin' => $data['coin'],
                'sales_num' => $data['sales_num'],
                'real_num' => $real_num,
                'surplus_num' =>$real_num,
                'sales_price' => $data['sales_price'],
                'fee' => $data['sales_num'] * ($fee / 100),
                'create_time' => time(),
                'update_time' => time()
            ];
            //判断用户账户余额
            $coin = CoinList::get($data['coin']);
            $user_coin = CoinUser::where(['user_id' => $this->user_id,'coin_id' => $data['coin'],'state' => 1])->find();
            if(!$user_coin)throw new Exception("暂未开通{$coin->name}账户");
            if($user_coin['avalible_price'] < $data['sales_num'])throw new Exception("账户可用余额不足");
            //扣除可用余额到冻结余额
            $update = [
                'avalible_price' => $user_coin['avalible_price'] - $data['sales_num'],
                'freezing_price' => $user_coin['freezing_price'] + $data['sales_num']
            ];
            CoinUser::where(['user_id' => $this->user_id,'coin_id' => $data['coin'],'state' => 1])->update($update);
            //添加求购记录
            TradeCnySales::create($res);
            Db::commit();
        } catch (Exception $e) {
            Db::rollback();
            return jsonError($e->getMessage());
        }
        return jsonSuccess('挂卖成功');
    }
    
    /**
     * 获取法币交易挂卖、出售订单信息
     * @return unknown
     */
    public function getSalesInfo()
    {
    	$id = $this->reqeust -> post('id');
    	$trade_style = $this->reqeust -> post('trade_style');
    	if($trade_style == 1) {
    		$info = TradeCnySales::get($id);
    	}else{
    		$info = TradeCnyBuy::get($id);
    	}
    	return jsonSuccess($info);
    }

    /**
     * 我要买
     */
    public function MateBuy()
    {
    	$this->checkReal($this->user_id);  //判断是否符合交易需求
        //防止重复下单
        if ($this->redis->get('user' . $this->user_id)) throw new Exception('请勿重复提交');
        $this->redis->set('user' . $this->user_id, 1);
        $data = $this->reqeust->post('');
        Db::startTrans();
        try {
            $list = TradeCnySales::get($data ['id']);
            //不能和自己匹配
            if ($list['user_id'] == $this->user_id) throw new Exception('无法与自己匹配');
            if ($list->surplus_num < $data ['mate_num'])
                throw new Exception ('系统错误');
            if (!$data ['mate_num'])
                throw new Exception ('请输入匹配数');
            //有没有这个币的账户
            $coin = CoinList::get($list->coin->id);
            $user_coin = CoinUser::where(['user_id' => $this->user_id, 'coin_id' => $list->coin->id, 'state' => 1])->find();
            if (!$user_coin) throw new Exception("暂未开通{$coin->name}账户");
            $out_trade_no = date('YmdHis') . rand(10, 99);
            $res = [
                'out_trade_no' => $out_trade_no,
                'sales_id' => $list->user_id,
                'buy_id' => $this->user_id,
                'mate_num' => $data ['mate_num'],
                'trade_type' => 2,
                'unit_price' => $list->sales_price,
                'total_price' => $data ['mate_num'] * $list->sales_price,
                'create_time' => time(),
                'source' => 2,
                'source_id' => $data ['id']
            ];
            // 添加我要买记录
            TradeMate::create($res);
            // 减去挂卖订单的挂卖数量
            TradeCnySales::where(['id' => $data ['id']])->setDec('surplus_num', $data ['mate_num']);
            Db::commit();
        } catch (Exception $e) {
            Db::rollback();
            $this->redis->delete('user' . $this->user_id);
            return jsonError($e->getMessage());
        }
        $this->redis->delete('user' . $this->user_id);
        return jsonSuccess('下单成功');
    }

    /**
     * 我要卖
     */
    public function MateSales()
    {
    	$this->checkReal($this->user_id);  //判断是否符合交易需求
        //防止重复下单
        if ($this->redis->get('user' . $this->user_id)) throw new Exception('请勿重复提交');
        $this->redis->set('user' . $this->user_id, 1);
        $data = $this->reqeust->post('');
        Db::startTrans();
        try {
            $list = TradeCnyBuy::get($data['id']);
            //不能和自己匹配
            if ($list['user_id'] == $this->user_id) throw new Exception('无法与自己匹配');
            if (!$data['mate_num']) throw new Exception('请输入匹配数');
            //判断订单剩余数量够不够
            if ($list->surplus_num < $data['mate_num']) throw new Exception("系统错误");
            //减去挂买订单的剩余数量
            TradeCnyBuy::where(['id' => $data['id']])->setDec('surplus_num', $data['mate_num']);
            //判断用户账户余额
            $coin = CoinList::get($list->coin->id);
            $user_coin = CoinUser::where(['user_id' => $this->user_id, 'coin_id' => $list->coin->id, 'state' => 1])->find();
            if (!$user_coin) throw new Exception("暂未开通{$coin->name}账户");
            if ($user_coin['avalible_price'] < $data['mate_num']) throw new Exception("账户可用余额不足");
            //扣除可用余额到冻结余额
            $update = [
                'avalible_price' => $user_coin['avalible_price'] - $data['mate_num'],
                'freezing_price' => $user_coin['freezing_price'] + $data['mate_num']
            ];
            CoinUser::where(['user_id' => $this->user_id, 'coin_id' => $list->coin, 'state' => 1])->update($update);
            $out_trade_no = date('YmdHis') . rand(10, 99);
            $res = [
                'out_trade_no' => $out_trade_no,
                'sales_id' => $this->user_id,
                'buy_id' => $list->user_id,
                'mate_num' => $data['mate_num'],
                'unit_price' => $list->buy_price,
                'total_price' => $data ['mate_num'] * $list->buy_price,
                'trade_type' => 2,
                'create_time' => time(),
                'source' => 1,
                'source_id' => $data['id'],
            ];
            //添加我要卖记录
            TradeMate::create($res);
            Db::commit();
        } catch (Exception $e) {
            Db::rollback();
            $this->redis->delete('user' . $this->user_id);
            return jsonError($e->getMessage());
        }
        $this->redis->delete('user' . $this->user_id);
        return jsonSuccess('下单成功');
    }

    /**
     * 订单详情
     */
    public function mateDetail()
    {
        $data = $this->reqeust->post('');
        $list = TradeMate::get($data['id'])->toArray();
        return jsonSuccess($list);
    }

    /**
     * 上传打款截图
     */
    public function payment()
    {
    	//获取客户端传递的临时文件
    	if(!empty($_FILES['file'])){
    		$file = $_FILES['file'];
    		$upload = new Base64();
    		try {
    			$res = $upload->uniAppUpload(Config::get('path.pay'), $file);
    			if(!$res)throw new Exception('图片上传失败');
    		} catch (Exception $e) {
    			return jsonError($e->getMessage());
    		}
    		return jsonSuccess($res);
    	}
    }
    
    /**
     * 订单打款
     * @throws Exception
     * @return unknown
     */
    public function tradePay()
    {
    	$data = $this->reqeust->post('');
    	try {
    		if(!$data['payment_voucher'])throw new Exception('请上传打款截图');
    		$trade_mate = TradeMate::get($data['id']);
    		if($trade_mate -> state !== 1)throw new Exception('请勿重复操作');
    		$data['state'] = 2;
    		$data['pay_time'] = time();
    		$trade_mate->save($data);
    	} catch (Exception $e) {
    		return jsonError($e->getMessage());
    	}
    	return jsonSuccess('打款成功');
    }

    /**
     * 申诉订单
     */
    public function complain()
    {
        $data = $this->reqeust->post('');
        if (!$data['content']) return jsonError('请填写申诉内容');
        if (!$data['img']) return jsonError('请上传申诉证明');
        $list = TradeMate::get($data['id']);
        $complain_id = $this->user_id == $list->sales_id->id ? $list->buy_id->id : $list->sales_id->id;
        $data['img'] = Base64::up_base64($data['img'], 'complain');
        $res = [
            'user_id' => $this->user_id,
            'complain_id' => $complain_id,
            'content' => $data['content'],
            'img' => $data['img'],
            'create_time' => time(),
            'mate_id' => $data['id'],
        ];
        //添加申诉记录
        TradeComplain::create($res);
        //更改订单状态
        TradeMate::where(['id' => $data['id']])->update(['state' => 4, 'complain_time' => time()]);
        return jsonSuccess('申诉成功');
    }

    /**
     * 确认收款
     */
    public function mateTrue()
    {
        //防止重复确认
    	if ($this->redis->get('user' . $this->user_id)) throw new Exception('请勿重复提交');
        $this->redis->set('user' . $this->user_id, 1);
        $data = $this->reqeust->post('');
        Db::startTrans();
        try {
            $list = TradeMate::get($data['id']);
            if($list->trade_type != 2)throw new Exception('非法操作');
            //获取交易币种
            $obj = $list->sales_id->id == $this->user_id ? new TradeCnySales() : new TradeCnyBuy();
            $trade = $obj->get($list->source_id);
            $coin_id = $trade->coin->id;
            //给买家账户加钱
            $buy = $list->buy_id->id;
            CoinUser::where(['user_id' => $buy, 'coin_id' => $coin_id])->setInc('avalible_price', $list->mate_num);
            //卖家
            $sales = $list->sales_id->id;
            //卖家冻结的钱去掉
            CoinUser::where(['user_id' => $sales, 'coin_id' => $coin_id])->setDec('freezing_price', $list->mate_num);
            //更改订单状态
            TradeMate::where(['id' => $data['id']])->update(['state' => 3, 'true_time' => time()]);
            Db::commit();
        } catch (Exception $e) {
            Db::rollback();
            $this->redis->delete('user' . $this->user_id);
            return jsonError($e->getMessage());
        }
        $this->redis->delete('user' . $this->user_id);
        return jsonSuccess('确认收款成功');
    }
}